package com.yida.gwj.expend.outside.aspect;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.SpelUtils;
import com.yida.common.security.utils.SecurityUtils;
import com.yida.gwj.api.service.RemoteGwjConfigService;
import com.yida.gwj.common.enums.StepConfigInfoEnum;
import com.yida.gwj.common.utils.GwjEnumUtils;
import com.yida.gwj.expend.outside.annotation.ConfStepConfigCheck;
import com.yida.gwj.expend.outside.enums.BusinessStatusEnum;
import com.yida.gwj.expend.outside.enums.FlagStatusEnum;
import com.yida.gwj.expend.outside.enums.MaintenanceFundsErrorEnum;
import com.yida.gwj.expend.outside.service.IGwjMaintenanceFundsBusinessService;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;

/**
 * 业务步骤检查
 *
 * @author liangp
 * @date 2023/03/02
 */
@Component
@Aspect
public class ConfStepConfigCheckAspect {

    private final Logger log = LoggerFactory.getLogger(ConfStepConfigCheckAspect.class);
    @Autowired
    private RemoteGwjConfigService remoteGwjConfigService;
    @Autowired
    private IGwjMaintenanceFundsBusinessService maintenanceFundsBusinessService;

    @Pointcut("@annotation(confStepConfigCheck)")
    public void pointCut(ConfStepConfigCheck confStepConfigCheck) {}

    @Before("pointCut(confStepConfigCheck)")
    public void before(JoinPoint joinPoint, ConfStepConfigCheck confStepConfigCheck) {
        log.info("业务步骤校验参数 -> [{}]", joinPoint);
        StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext(joinPoint.getArgs());
        standardEvaluationContext = SpelUtils.setContextVariables(standardEvaluationContext, joinPoint);
        Optional<Long> bizId = SpelUtils.getElValue(Long.class, confStepConfigCheck.bizId(), standardEvaluationContext);
        if (!bizId.isPresent()) {
            return;
        }
        Optional.ofNullable(maintenanceFundsBusinessService.selectGwjMaintenanceFundsBusinessByBusinessId(bizId.get())).ifPresent((maintenanceFundsBusiness) -> {
            MethodSignature signature = (MethodSignature)joinPoint.getSignature();
            ConfStepConfigCheck configCheck = signature.getMethod().getAnnotation(ConfStepConfigCheck.class);

            // 1.判断当前用户是有有操作权限
            Optional<FlagStatusEnum> flagStatus = Optional.ofNullable(configCheck.checkUser());
            flagStatus.ifPresent(flag -> {
                if (ObjectUtil.equal(flag.getCode(), FlagStatusEnum.FAL.getCode())) {
                    return;
                }
                if (ObjectUtil.notEqual(SecurityUtils.getLoginUser().getUserid(), maintenanceFundsBusiness.getApplicantUserId())) {
                    throw new ServiceException(GwjEnumUtils.getEnumConstantMsg(MaintenanceFundsErrorEnum.ACCEPT_USER_CHECK) + "受理人员不一致");
                }
            });
            // 2.判断当前操作是否包含预想的步骤按钮权限
            Optional<StepConfigInfoEnum[]> stepConfigInfos = Optional.ofNullable(configCheck.stepConfigInfo());
            stepConfigInfos.ifPresent(stepInfos -> {
                List<Integer> businessStatusList = Arrays.stream(stepInfos).map(StepConfigInfoEnum::getNo).collect(Collectors.toList());
                if (CollectionUtil.contains(businessStatusList, StepConfigInfoEnum.NULL.getNo())) {
                    return;
                }
                List<String> configInfos;
                try {
                    configInfos = remoteGwjConfigService.selectGwjConfStepConfigInfoCodeListByBizFlagId(maintenanceFundsBusiness.getStepId(), SecurityConstants.INNER).getData();
                } catch (Exception e) {
                    throw new ServiceException(GwjEnumUtils.getEnumConstantMsg(MaintenanceFundsErrorEnum.CONF_STEP_CONFIG_CHECK) + "远程调用 -> remoteGwjConfigService异常");
                }
                List<String> stepConfigInfoList = Arrays.stream(stepConfigInfos.get()).map(StepConfigInfoEnum::getCode).collect(Collectors.toList());
                if (!CollectionUtil.containsAny(configInfos, stepConfigInfoList)) {
                    throw new ServiceException(GwjEnumUtils.getEnumConstantMsg(MaintenanceFundsErrorEnum.CONF_STEP_CONFIG_CHECK) + "当前步骤信息不匹配");
                }
            });
            // 3.判断当前操作是否包含预想的业务状态
            Optional<BusinessStatusEnum[]> businessStatus = Optional.ofNullable(configCheck.businessStatus());
            businessStatus.ifPresent(business -> {
                List<Integer> businessStatusList = Arrays.stream(business).map(BusinessStatusEnum::getCode).collect(Collectors.toList());
                if (CollectionUtil.contains(businessStatusList, BusinessStatusEnum.NULL.getCode())) {
                    return;
                }
                if (!CollectionUtil.contains(businessStatusList, maintenanceFundsBusiness.getStatus())) {
                    throw new ServiceException(GwjEnumUtils.getEnumConstantMsg(MaintenanceFundsErrorEnum.CONF_STEP_CONFIG_CHECK) + "当前业务信息不匹配");
                }
            });
        });
    }
}
